Load Packages

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.7     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1
── Conflicts ─────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(ggthemes)
library(scales)

Attaching package: ‘scales’

The following object is masked from ‘package:purrr’:

    discard

The following object is masked from ‘package:readr’:

    col_factor
library(readxl)
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout

Making Dataframes

color_a <- c("#58b5e1","#1c5b5a","#46ebdc","#1f4196","#e28de2","#818bd7","#e4ccf1","#82185f","#f849b6","#000000","#5e34bc","#b7d165","#30d52e","#ff5357")
color_na <- c("#1c5b5a","#46ebdc","#1f4196","#e28de2","#818bd7","#e4ccf1","#82185f","#f849b6","#000000","#5e34bc","#b7d165","#30d52e","#ff5357")
counties <- c('Anson', 'Cabarrus', 'Catawba', 'Chester', 'Cleveland', 'Gaston', 'Iredell', 'Lancaster', 'Lincoln', 'Mecklenburg', 'Rowan', 'Stanly', 'Union', 'York')
attainment_lvl <- c('Highest Degree: Less than a High School Diploma', 'Highest Degree: High School Diploma', 'Highest Degree: Some College, No Degree', "Highest Degree: Associate's Degree", "Highest Degree: Bachelor's Degree", "Highest Degree: Graduate or Professional Degree")
foreign_detail <- c('Foreign-Born: Africa', 'Foreign-Born: Asia', 'Foreign-Born: Europe', 'Foreign-Born: Latin America', 'Place of Birth Total')

countypop <- rbind(read_csv("cc-est2019-agesex-37.csv", show_col_types = F),
                   read_csv("cc-est2019-agesex-45.csv", show_col_types = F)) %>%
  select(-SUMLEV, -STATE, -COUNTY) %>%
  mutate(CTYNAME = gsub(' County', '', CTYNAME),
         YEAR = as.integer(YEAR + 2007)) %>%
  filter(CTYNAME %in% counties, YEAR >= 2010,
         !(STNAME == 'South Carolina' & CTYNAME == 'Union')) %>%
  distinct()
# Year 3 is 2010, Year 12 is 2019

# Making Charlotte Region
cr <- countypop[1:10,] %>%
  mutate(CTYNAME = 'Charlotte Region')
for(i in 4:length(colnames(countypop))) {
  for(j in 1:10){
    cr[j,i] <- sum((countypop %>% filter(YEAR == j+2009))[i])
  }
}

# Making Age & Gender data frame
pop_age_gender <- rbind(countypop, cr)
countypop <- cr %>% transmute(YEAR = YEAR, CHARLOTTEPOP = POPESTIMATE) %>% right_join(countypop, by = 'YEAR') %>% mutate(PROPORTION = POPESTIMATE / CHARLOTTEPOP) %>%
  group_by(CTYNAME) %>%
  mutate(CHANGE = ifelse(YEAR == 2010, 0, POPESTIMATE/lag(POPESTIMATE, default = first(YEAR)) - 1)) %>%
  ungroup()

pop_age_gender <- pop_age_gender %>%
  select(-contains('_TOT'), -POPEST_FEM, -POPEST_MALE, -AGE16PLUS_MALE, -AGE16PLUS_FEM, -AGE18PLUS_FEM, -AGE18PLUS_MALE, -UNDER5_FEM, -UNDER5_MALE, -AGE1544_FEM, -AGE1544_MALE, -MEDIAN_AGE_FEM, -MEDIAN_AGE_MALE, -AGE65PLUS_FEM,-AGE65PLUS_MALE, -AGE513_FEM, -AGE513_MALE, -AGE4564_FEM, -AGE4564_MALE, -AGE2544_FEM, -AGE2544_MALE, -AGE1824_FEM, -AGE1824_MALE, -AGE1417_FEM, -AGE1417_MALE) %>%
  rename(AGE004_FEM = AGE04_FEM, AGE004_MALE = AGE04_MALE, AGE0509_MALE = AGE59_MALE, AGE0509_FEM = AGE59_FEM)
pop_age_gender <- pop_age_gender %>%
  pivot_longer(cols = colnames(pop_age_gender[,5:40]), names_to = 'DEMO', values_to = 'POP') %>%
  mutate(PERCENTAGE = POP/POPESTIMATE)
pop_age_gender <- pop_age_gender %>%
  mutate(GENDER = as.factor(ifelse(grepl('MALE', pop_age_gender$DEMO),'MALE','FEMALE')),
         DEMO = gsub('_FEM','', DEMO),
         DEMO = gsub('_MALE','', DEMO),
         DEMO = case_when(DEMO == 'AGE004' ~ '0-04',
                          DEMO == 'AGE0509' ~ '05-09',
                          DEMO == 'AGE1014' ~ '10-14',
                          DEMO == 'AGE1519' ~ '15-19',
                          DEMO == 'AGE2024' ~ '20-24',
                          DEMO == 'AGE2529' ~ '25-29',
                          DEMO == 'AGE3034' ~ '30-34',
                          DEMO == 'AGE3539' ~ '35-39',
                          DEMO == 'AGE4044' ~ '40-44',
                          DEMO == 'AGE4549' ~ '45-49',
                          DEMO == 'AGE5054' ~ '50-54',
                          DEMO == 'AGE5559' ~ '55-59',
                          DEMO == 'AGE6064' ~ '60-64',
                          DEMO == 'AGE6569' ~ '65-69',
                          DEMO == 'AGE7074' ~ '70-74',
                          DEMO == 'AGE7579' ~ '75-79',
                          DEMO == 'AGE8084' ~ '80-84',
                          DEMO == 'AGE85PLUS' ~ '85 and Over'))

# Making ethnicity data frame
ethpop <- rbind(read_csv("cc-est2019-alldata-37.csv", show_col_types = F),
                   read_csv("cc-est2019-alldata-45.csv", show_col_types = F)) %>%
  mutate(CTYNAME = gsub(' County', '', CTYNAME),
         YEAR = as.integer(YEAR + 2007),
         WHITE = NHWA_MALE + NHWA_FEMALE,
         BLACK = NHBA_MALE + NHBA_FEMALE,
         HISPANIC = HWA_MALE + HWA_FEMALE + HBA_MALE + HBA_FEMALE + HIA_MALE + HIA_FEMALE + HAA_MALE + HAA_FEMALE + HNA_MALE + HNA_FEMALE + HIA_MALE + HIA_FEMALE,
         ASIAN = NHAA_MALE + NHAA_FEMALE,
         ISLANDER = NHNA_MALE + NHNA_FEMALE,
         NATIVE = NHIA_MALE + NHIA_FEMALE,
         MULTIRACIAL = TOM_MALE + TOM_FEMALE - HTOM_MALE - HTOM_FEMALE
         ) %>%
  filter(CTYNAME %in% counties, YEAR >= 3, AGEGRP == 0,
         !(STNAME == 'South Carolina' & CTYNAME == 'Union')) %>%
  select(STNAME, CTYNAME, YEAR, TOT_POP, WHITE, BLACK, HISPANIC, ASIAN, ISLANDER, NATIVE, MULTIRACIAL) %>%
  distinct()
ethpop <- ethpop %>%
  pivot_longer(cols = colnames(ethpop[,5:11]), names_to = 'ETHNICITY', values_to = 'POP')

# Making place of birth data frame
birthplace <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Indicator == 'Place of Birth',
         County %in% counties,
         !(Measure %in% foreign_detail)) %>%
  distinct()
birthplace <- birthplace %>% inner_join((birthplace %>% group_by(County, Year) %>% summarise(Total = sum(Numerator_value))), by = c('County', 'Year'))
`summarise()` has grouped output by 'County'. You can
override using the `.groups` argument.
# Making the unemployment data frame
unemployment <- rbind(read_excel('ur_anson.xlsx', trim_ws = T) %>% mutate(County = 'Anson', Period = gsub('M', '', Period)),
                      read_excel('ur_cabarrus.xlsx', trim_ws = T) %>% mutate(County = 'Cabarrus', Period = gsub('M', '', Period)),
                      read_excel('ur_catawba.xlsx', trim_ws = T) %>% mutate(County = 'Catawba', Period = gsub('M', '', Period)),
                      read_excel('ur_chester.xlsx', trim_ws=T, skip=11)[1:266,] %>% rename(Value = 'Observation Value') %>% mutate(County = 'Chester', Period = gsub('M','',Period)) %>% select(-Label),
                      read_excel('ur_cleveland.xlsx', trim_ws = T) %>% mutate(County = 'Cleveland', Period = gsub('M', '', Period)),
                      read_excel('ur_gaston.xlsx', trim_ws = T) %>% mutate(County = 'Gaston', Period = gsub('M', '', Period)),
                      read_excel('ur_iredell.xlsx', trim_ws = T) %>% mutate(County = 'Iredell', Period = gsub('M', '', Period)),
                      read_excel('ur_lancaster.xlsx', trim_ws = T) %>% mutate(County = 'Lancaster', Period = gsub('M', '', Period)),
                      read_excel('ur_lincoln.xlsx', trim_ws = T) %>% mutate(County = 'Lincoln', Period = gsub('M', '', Period)),
                      read_excel('ur_mecklenburg.xlsx', trim_ws = T) %>% mutate(County = 'Mecklenburg', Period = gsub('M', '', Period)),
                      read_excel('ur_rowan.xlsx', trim_ws = T) %>% mutate(County = 'Rowan', Period = gsub('M', '', Period)),
                      read_excel('ur_stanly.xlsx', trim_ws=T, skip=11)[1:266,] %>% rename(Value = 'Observation Value') %>% mutate(County = 'Stanly', Period = gsub('M','',Period)) %>% select(-Label),
                      read_excel('ur_union.xlsx', trim_ws = T) %>% mutate(County = 'Union', Period = gsub('M', '', Period)),
                      read_excel('ur_york.xlsx', trim_ws = T) %>% mutate(County = 'York', Period = gsub('M', '', Period))) %>%
  mutate(Year = as.integer(Year),
         Period = as.integer(Period),
         Date = as.Date(paste(Year,'-',Period, '-01', sep = '')),
         Value = Value/100) %>%
  rename(Month = Period,
         Unemployment = Value)

# Make income data frame
income <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Indicator == 'Income & Earnings',
         County %in% counties,
         Measure != 'Household Income: Total') %>%
  distinct()
income <- income %>% inner_join((income %>% group_by(County, Year) %>% summarise(Total = sum(Numerator_value))), by = c('County', 'Year'))
`summarise()` has grouped output by 'County'. You can
override using the `.groups` argument.
# Make education attainment data frame
education <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Indicator == 'Educational Attainment',
         County %in% counties,
         Measure %in% attainment_lvl) %>%
  distinct()
education <- education %>% inner_join((education %>% group_by(County, Year) %>% summarise(Total = sum(Numerator_value))), by = c('County', 'Year')) %>%
  mutate(Order = as.factor(case_when(
    Measure == 'Highest Degree: Less than a High School Diploma' ~ 1,
    Measure == 'Highest Degree: High School Diploma' ~ 2,
    Measure == 'Highest Degree: Some College, No Degree' ~ 3,
    Measure == "Highest Degree: Associate's Degree" ~ 4,
    Measure == "Highest Degree: Bachelor's Degree" ~ 5,
    Measure == "Highest Degree: Graduate or Professional Degree" ~ 6)))
`summarise()` has grouped output by 'County'. You can
override using the `.groups` argument.
# Make health care coverage data frame
coverage <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Indicator == 'Health Care Coverage',
         County %in% counties)
# Make housing age data frame
housing <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Indicator == 'Housing Stock',
         County %in% counties)
# Make poverty figures data frame
poverty <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Measure == 'Individuals in Poverty',
         Theme == 'Social Well-Being',
         County %in% counties)
# Make transportation means data frame
transportation <- read.csv('Values.csv') %>%
  mutate(County = gsub(' County, North Carolina', '', County),
         County = gsub(' County, South Carolina', '', County)) %>%
  filter(Theme == 'Transportation',
         Measure != 'Commuting Means Total',
         County %in% counties)

Demographics

Population

plot_ly(countypop %>% filter(YEAR == 2019), x = ~POPESTIMATE, y = ~CTYNAME, type = 'bar', color = ~CTYNAME, colors = color_a, orientation = 'h')

plot_ly(countypop, x=~YEAR, y=~CHANGE, color=~CTYNAME, type='scatter', mode='lines', colors=color_a)

Age & Gender

plot_ly(pop_age_gender %>% filter(YEAR == 2017, CTYNAME == 'Charlotte Region', GENDER == "MALE"),
        y=~DEMO, x=~PERCENTAGE,
        type='bar', name = 'Male') %>%
  add_trace(data = pop_age_gender %>% filter(YEAR == 2017, CTYNAME == 'Charlotte Region', GENDER == "FEMALE"), y=~DEMO, name = 'Female')

Race & Ethnicity

plot_ly(ethpop %>% filter(YEAR == 2019),
        y=~CTYNAME, x=~POP/TOT_POP, color=~ETHNICITY,
        type='bar') %>%
  layout(barmode = 'stack')

Place of Birth

plot_ly(birthplace %>% filter(Year == 2019),
        y=~County, x=~Numerator_value/Total, color=~Measure,
        type='bar') %>%
  layout(barmode = 'stack')

Economy

Unemployment

plot_ly(unemployment, x=~Date, y=~Unemployment, color=~County, colors=color_a, type='scatter', mode='lines')

plot_ly(unemployment %>% filter(Year==2015, Month==6), x=~Unemployment, y=~County, color=~County, colors=color_a, type='bar')

Income

#### DFs from Values.csv are missing Anson, Chester, and Stanly Counties
ggplot(income %>% filter(Year == 2014), aes(x = County, y = (Numerator_value / Total), fill = Measure), position = 'fill') +
  geom_col() +
  scale_y_continuous(labels = scales::percent) +
  coord_flip()

Education

Educational Attainment

ggplot(arrange(education, Order) %>% filter(Year == 2014), aes(x = County, y = (Numerator_value / Total), fill = Order), position = 'fill') +
  geom_col() +
  scale_y_continuous(labels = scales::percent) +
  coord_flip()+
  scale_fill_discrete(labels = attainment_lvl, name = '')

Health

Health Care Coverage

coverage %>% filter(Measure == "Health Insurance Total", Year == 2017) %>%
  ggplot(., aes(x = County, y = Numerator_value, fill = County))+
  geom_col() +
  scale_y_continuous(labels = comma) +
  coord_flip()

coverage %>% filter(Year == 2017, !(Measure %in% c("Health Insurance Total", "People with Health Insurance"))) %>%
  ggplot(aes(x = County, y = Numerator_value, fill = Measure, position = Measure)) +
  geom_col(position = "dodge") +
  scale_y_continuous(labels = comma) +
  coord_flip()

Housing

Housing Age

housing %>% filter(Year == 2017) %>%
  ggplot(aes(x= County, y = Year-Numerator_value, fill = County)) +
  geom_col() +
  coord_flip()

Social Well-Being

Poverty

poverty %>% filter(Year == 2010) %>%
  ggplot(., aes(x = County, y = Numerator_value/Denominator_value, fill = County)) +
  geom_col() +
  coord_flip()
Warning: Removed 1 rows containing missing values (position_stack).

Transportation

##Commuting Modes

# Way too many missing values to create a substantive visualization.
transportation %>% filter(Year == 2014) %>%
  ggplot(aes(x = County, y = Numerator_value, fill = Measure, position = Measure)) +
  geom_col(position = 'dodge') +
  scale_y_continuous(labels = comma) +
  coord_flip()
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIExvYWQgUGFja2FnZXMNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkocGxvdGx5KQ0KYGBgDQoNCg0KIyBNYWtpbmcgRGF0YWZyYW1lcw0KYGBge3J9DQpjb2xvcl9hIDwtIGMoIiM1OGI1ZTEiLCIjMWM1YjVhIiwiIzQ2ZWJkYyIsIiMxZjQxOTYiLCIjZTI4ZGUyIiwiIzgxOGJkNyIsIiNlNGNjZjEiLCIjODIxODVmIiwiI2Y4NDliNiIsIiMwMDAwMDAiLCIjNWUzNGJjIiwiI2I3ZDE2NSIsIiMzMGQ1MmUiLCIjZmY1MzU3IikNCmNvbG9yX25hIDwtIGMoIiMxYzViNWEiLCIjNDZlYmRjIiwiI2UyOGRlMiIsIiM4MThiZDciLCIjZTRjY2YxIiwiIzgyMTg1ZiIsIiNmODQ5YjYiLCIjMDAwMDAwIiwiIzVlMzRiYyIsIiMzMGQ1MmUiLCIjZmY1MzU3IikNCmNvdW50aWVzIDwtIGMoJ0Fuc29uJywgJ0NhYmFycnVzJywgJ0NhdGF3YmEnLCAnQ2hlc3RlcicsICdDbGV2ZWxhbmQnLCAnR2FzdG9uJywgJ0lyZWRlbGwnLCAnTGFuY2FzdGVyJywgJ0xpbmNvbG4nLCAnTWVja2xlbmJ1cmcnLCAnUm93YW4nLCAnU3Rhbmx5JywgJ1VuaW9uJywgJ1lvcmsnKQ0KYXR0YWlubWVudF9sdmwgPC0gYygnSGlnaGVzdCBEZWdyZWU6IExlc3MgdGhhbiBhIEhpZ2ggU2Nob29sIERpcGxvbWEnLCAnSGlnaGVzdCBEZWdyZWU6IEhpZ2ggU2Nob29sIERpcGxvbWEnLCAnSGlnaGVzdCBEZWdyZWU6IFNvbWUgQ29sbGVnZSwgTm8gRGVncmVlJywgIkhpZ2hlc3QgRGVncmVlOiBBc3NvY2lhdGUncyBEZWdyZWUiLCAiSGlnaGVzdCBEZWdyZWU6IEJhY2hlbG9yJ3MgRGVncmVlIiwgIkhpZ2hlc3QgRGVncmVlOiBHcmFkdWF0ZSBvciBQcm9mZXNzaW9uYWwgRGVncmVlIikNCmZvcmVpZ25fZGV0YWlsIDwtIGMoJ0ZvcmVpZ24tQm9ybjogQWZyaWNhJywgJ0ZvcmVpZ24tQm9ybjogQXNpYScsICdGb3JlaWduLUJvcm46IEV1cm9wZScsICdGb3JlaWduLUJvcm46IExhdGluIEFtZXJpY2EnLCAnUGxhY2Ugb2YgQmlydGggVG90YWwnKQ0KDQpjb3VudHlwb3AgPC0gcmJpbmQocmVhZF9jc3YoImNjLWVzdDIwMTktYWdlc2V4LTM3LmNzdiIsIHNob3dfY29sX3R5cGVzID0gRiksDQogICAgICAgICAgICAgICAgICAgcmVhZF9jc3YoImNjLWVzdDIwMTktYWdlc2V4LTQ1LmNzdiIsIHNob3dfY29sX3R5cGVzID0gRikpICU+JQ0KICBzZWxlY3QoLVNVTUxFViwgLVNUQVRFLCAtQ09VTlRZKSAlPiUNCiAgbXV0YXRlKENUWU5BTUUgPSBnc3ViKCcgQ291bnR5JywgJycsIENUWU5BTUUpLA0KICAgICAgICAgWUVBUiA9IGFzLmludGVnZXIoWUVBUiArIDIwMDcpKSAlPiUNCiAgZmlsdGVyKENUWU5BTUUgJWluJSBjb3VudGllcywgWUVBUiA+PSAyMDEwLA0KICAgICAgICAgIShTVE5BTUUgPT0gJ1NvdXRoIENhcm9saW5hJyAmIENUWU5BTUUgPT0gJ1VuaW9uJykpICU+JQ0KICBkaXN0aW5jdCgpDQojIFllYXIgMyBpcyAyMDEwLCBZZWFyIDEyIGlzIDIwMTkNCg0KIyBNYWtpbmcgQ2hhcmxvdHRlIFJlZ2lvbg0KY3IgPC0gY291bnR5cG9wWzE6MTAsXSAlPiUNCiAgbXV0YXRlKENUWU5BTUUgPSAnQ2hhcmxvdHRlIFJlZ2lvbicpDQpmb3IoaSBpbiA0Omxlbmd0aChjb2xuYW1lcyhjb3VudHlwb3ApKSkgew0KICBmb3IoaiBpbiAxOjEwKXsNCiAgICBjcltqLGldIDwtIHN1bSgoY291bnR5cG9wICU+JSBmaWx0ZXIoWUVBUiA9PSBqKzIwMDkpKVtpXSkNCiAgfQ0KfQ0KDQojIE1ha2luZyBBZ2UgJiBHZW5kZXIgZGF0YSBmcmFtZQ0KcG9wX2FnZV9nZW5kZXIgPC0gcmJpbmQoY291bnR5cG9wLCBjcikNCmNvdW50eXBvcCA8LSBjciAlPiUgdHJhbnNtdXRlKFlFQVIgPSBZRUFSLCBDSEFSTE9UVEVQT1AgPSBQT1BFU1RJTUFURSkgJT4lIHJpZ2h0X2pvaW4oY291bnR5cG9wLCBieSA9ICdZRUFSJykgJT4lIG11dGF0ZShQUk9QT1JUSU9OID0gUE9QRVNUSU1BVEUgLyBDSEFSTE9UVEVQT1ApICU+JQ0KICBncm91cF9ieShDVFlOQU1FKSAlPiUNCiAgbXV0YXRlKENIQU5HRSA9IGlmZWxzZShZRUFSID09IDIwMTAsIDAsIFBPUEVTVElNQVRFL2xhZyhQT1BFU1RJTUFURSwgZGVmYXVsdCA9IGZpcnN0KFlFQVIpKSAtIDEpKSAlPiUNCiAgdW5ncm91cCgpDQoNCnBvcF9hZ2VfZ2VuZGVyIDwtIHBvcF9hZ2VfZ2VuZGVyICU+JQ0KICBzZWxlY3QoLWNvbnRhaW5zKCdfVE9UJyksIC1QT1BFU1RfRkVNLCAtUE9QRVNUX01BTEUsIC1BR0UxNlBMVVNfTUFMRSwgLUFHRTE2UExVU19GRU0sIC1BR0UxOFBMVVNfRkVNLCAtQUdFMThQTFVTX01BTEUsIC1VTkRFUjVfRkVNLCAtVU5ERVI1X01BTEUsIC1BR0UxNTQ0X0ZFTSwgLUFHRTE1NDRfTUFMRSwgLU1FRElBTl9BR0VfRkVNLCAtTUVESUFOX0FHRV9NQUxFLCAtQUdFNjVQTFVTX0ZFTSwtQUdFNjVQTFVTX01BTEUsIC1BR0U1MTNfRkVNLCAtQUdFNTEzX01BTEUsIC1BR0U0NTY0X0ZFTSwgLUFHRTQ1NjRfTUFMRSwgLUFHRTI1NDRfRkVNLCAtQUdFMjU0NF9NQUxFLCAtQUdFMTgyNF9GRU0sIC1BR0UxODI0X01BTEUsIC1BR0UxNDE3X0ZFTSwgLUFHRTE0MTdfTUFMRSkgJT4lDQogIHJlbmFtZShBR0UwMDRfRkVNID0gQUdFMDRfRkVNLCBBR0UwMDRfTUFMRSA9IEFHRTA0X01BTEUsIEFHRTA1MDlfTUFMRSA9IEFHRTU5X01BTEUsIEFHRTA1MDlfRkVNID0gQUdFNTlfRkVNKQ0KcG9wX2FnZV9nZW5kZXIgPC0gcG9wX2FnZV9nZW5kZXIgJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gY29sbmFtZXMocG9wX2FnZV9nZW5kZXJbLDU6NDBdKSwgbmFtZXNfdG8gPSAnREVNTycsIHZhbHVlc190byA9ICdQT1AnKSAlPiUNCiAgbXV0YXRlKFBFUkNFTlRBR0UgPSBQT1AvUE9QRVNUSU1BVEUpDQpwb3BfYWdlX2dlbmRlciA8LSBwb3BfYWdlX2dlbmRlciAlPiUNCiAgbXV0YXRlKEdFTkRFUiA9IGFzLmZhY3RvcihpZmVsc2UoZ3JlcGwoJ01BTEUnLCBwb3BfYWdlX2dlbmRlciRERU1PKSwnTUFMRScsJ0ZFTUFMRScpKSwNCiAgICAgICAgIERFTU8gPSBnc3ViKCdfRkVNJywnJywgREVNTyksDQogICAgICAgICBERU1PID0gZ3N1YignX01BTEUnLCcnLCBERU1PKSwNCiAgICAgICAgIERFTU8gPSBjYXNlX3doZW4oREVNTyA9PSAnQUdFMDA0JyB+ICcwLTA0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgREVNTyA9PSAnQUdFMDUwOScgfiAnMDUtMDknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBERU1PID09ICdBR0UxMDE0JyB+ICcxMC0xNCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgIERFTU8gPT0gJ0FHRTE1MTknIH4gJzE1LTE5JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgREVNTyA9PSAnQUdFMjAyNCcgfiAnMjAtMjQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBERU1PID09ICdBR0UyNTI5JyB+ICcyNS0yOScsDQogICAgICAgICAgICAgICAgICAgICAgICAgIERFTU8gPT0gJ0FHRTMwMzQnIH4gJzMwLTM0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgREVNTyA9PSAnQUdFMzUzOScgfiAnMzUtMzknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBERU1PID09ICdBR0U0MDQ0JyB+ICc0MC00NCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgIERFTU8gPT0gJ0FHRTQ1NDknIH4gJzQ1LTQ5JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgREVNTyA9PSAnQUdFNTA1NCcgfiAnNTAtNTQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBERU1PID09ICdBR0U1NTU5JyB+ICc1NS01OScsDQogICAgICAgICAgICAgICAgICAgICAgICAgIERFTU8gPT0gJ0FHRTYwNjQnIH4gJzYwLTY0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgREVNTyA9PSAnQUdFNjU2OScgfiAnNjUtNjknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBERU1PID09ICdBR0U3MDc0JyB+ICc3MC03NCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgIERFTU8gPT0gJ0FHRTc1NzknIH4gJzc1LTc5JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgREVNTyA9PSAnQUdFODA4NCcgfiAnODAtODQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBERU1PID09ICdBR0U4NVBMVVMnIH4gJzg1IGFuZCBPdmVyJykpDQoNCiMgTWFraW5nIGV0aG5pY2l0eSBkYXRhIGZyYW1lDQpldGhwb3AgPC0gcmJpbmQocmVhZF9jc3YoImNjLWVzdDIwMTktYWxsZGF0YS0zNy5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEYpLA0KICAgICAgICAgICAgICAgICAgIHJlYWRfY3N2KCJjYy1lc3QyMDE5LWFsbGRhdGEtNDUuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGKSkgJT4lDQogIG11dGF0ZShDVFlOQU1FID0gZ3N1YignIENvdW50eScsICcnLCBDVFlOQU1FKSwNCiAgICAgICAgIFlFQVIgPSBhcy5pbnRlZ2VyKFlFQVIgKyAyMDA3KSwNCiAgICAgICAgIFdISVRFID0gTkhXQV9NQUxFICsgTkhXQV9GRU1BTEUsDQogICAgICAgICBCTEFDSyA9IE5IQkFfTUFMRSArIE5IQkFfRkVNQUxFLA0KICAgICAgICAgSElTUEFOSUMgPSBIV0FfTUFMRSArIEhXQV9GRU1BTEUgKyBIQkFfTUFMRSArIEhCQV9GRU1BTEUgKyBISUFfTUFMRSArIEhJQV9GRU1BTEUgKyBIQUFfTUFMRSArIEhBQV9GRU1BTEUgKyBITkFfTUFMRSArIEhOQV9GRU1BTEUgKyBISUFfTUFMRSArIEhJQV9GRU1BTEUsDQogICAgICAgICBBU0lBTiA9IE5IQUFfTUFMRSArIE5IQUFfRkVNQUxFLA0KICAgICAgICAgSVNMQU5ERVIgPSBOSE5BX01BTEUgKyBOSE5BX0ZFTUFMRSwNCiAgICAgICAgIE5BVElWRSA9IE5ISUFfTUFMRSArIE5ISUFfRkVNQUxFLA0KICAgICAgICAgTVVMVElSQUNJQUwgPSBUT01fTUFMRSArIFRPTV9GRU1BTEUgLSBIVE9NX01BTEUgLSBIVE9NX0ZFTUFMRQ0KICAgICAgICAgKSAlPiUNCiAgZmlsdGVyKENUWU5BTUUgJWluJSBjb3VudGllcywgWUVBUiA+PSAzLCBBR0VHUlAgPT0gMCwNCiAgICAgICAgICEoU1ROQU1FID09ICdTb3V0aCBDYXJvbGluYScgJiBDVFlOQU1FID09ICdVbmlvbicpKSAlPiUNCiAgc2VsZWN0KFNUTkFNRSwgQ1RZTkFNRSwgWUVBUiwgVE9UX1BPUCwgV0hJVEUsIEJMQUNLLCBISVNQQU5JQywgQVNJQU4sIElTTEFOREVSLCBOQVRJVkUsIE1VTFRJUkFDSUFMKSAlPiUNCiAgZGlzdGluY3QoKQ0KZXRocG9wIDwtIGV0aHBvcCAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb2xuYW1lcyhldGhwb3BbLDU6MTFdKSwgbmFtZXNfdG8gPSAnRVRITklDSVRZJywgdmFsdWVzX3RvID0gJ1BPUCcpDQoNCiMgTWFraW5nIHBsYWNlIG9mIGJpcnRoIGRhdGEgZnJhbWUNCmJpcnRocGxhY2UgPC0gcmVhZC5jc3YoJ1ZhbHVlcy5jc3YnKSAlPiUNCiAgbXV0YXRlKENvdW50eSA9IGdzdWIoJyBDb3VudHksIE5vcnRoIENhcm9saW5hJywgJycsIENvdW50eSksDQogICAgICAgICBDb3VudHkgPSBnc3ViKCcgQ291bnR5LCBTb3V0aCBDYXJvbGluYScsICcnLCBDb3VudHkpKSAlPiUNCiAgZmlsdGVyKEluZGljYXRvciA9PSAnUGxhY2Ugb2YgQmlydGgnLA0KICAgICAgICAgQ291bnR5ICVpbiUgY291bnRpZXMsDQogICAgICAgICAhKE1lYXN1cmUgJWluJSBmb3JlaWduX2RldGFpbCkpICU+JQ0KICBkaXN0aW5jdCgpDQpiaXJ0aHBsYWNlIDwtIGJpcnRocGxhY2UgJT4lIGlubmVyX2pvaW4oKGJpcnRocGxhY2UgJT4lIGdyb3VwX2J5KENvdW50eSwgWWVhcikgJT4lIHN1bW1hcmlzZShUb3RhbCA9IHN1bShOdW1lcmF0b3JfdmFsdWUpKSksIGJ5ID0gYygnQ291bnR5JywgJ1llYXInKSkNCg0KIyBNYWtpbmcgdGhlIHVuZW1wbG95bWVudCBkYXRhIGZyYW1lDQp1bmVtcGxveW1lbnQgPC0gcmJpbmQocmVhZF9leGNlbCgndXJfYW5zb24ueGxzeCcsIHRyaW1fd3MgPSBUKSAlPiUgbXV0YXRlKENvdW50eSA9ICdBbnNvbicsIFBlcmlvZCA9IGdzdWIoJ00nLCAnJywgUGVyaW9kKSksDQogICAgICAgICAgICAgICAgICAgICAgcmVhZF9leGNlbCgndXJfY2FiYXJydXMueGxzeCcsIHRyaW1fd3MgPSBUKSAlPiUgbXV0YXRlKENvdW50eSA9ICdDYWJhcnJ1cycsIFBlcmlvZCA9IGdzdWIoJ00nLCAnJywgUGVyaW9kKSksDQogICAgICAgICAgICAgICAgICAgICAgcmVhZF9leGNlbCgndXJfY2F0YXdiYS54bHN4JywgdHJpbV93cyA9IFQpICU+JSBtdXRhdGUoQ291bnR5ID0gJ0NhdGF3YmEnLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpLA0KICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZXhjZWwoJ3VyX2NoZXN0ZXIueGxzeCcsIHRyaW1fd3M9VCwgc2tpcD0xMSlbMToyNjYsXSAlPiUgcmVuYW1lKFZhbHVlID0gJ09ic2VydmF0aW9uIFZhbHVlJykgJT4lIG11dGF0ZShDb3VudHkgPSAnQ2hlc3RlcicsIFBlcmlvZCA9IGdzdWIoJ00nLCcnLFBlcmlvZCkpICU+JSBzZWxlY3QoLUxhYmVsKSwNCiAgICAgICAgICAgICAgICAgICAgICByZWFkX2V4Y2VsKCd1cl9jbGV2ZWxhbmQueGxzeCcsIHRyaW1fd3MgPSBUKSAlPiUgbXV0YXRlKENvdW50eSA9ICdDbGV2ZWxhbmQnLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpLA0KICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZXhjZWwoJ3VyX2dhc3Rvbi54bHN4JywgdHJpbV93cyA9IFQpICU+JSBtdXRhdGUoQ291bnR5ID0gJ0dhc3RvbicsIFBlcmlvZCA9IGdzdWIoJ00nLCAnJywgUGVyaW9kKSksDQogICAgICAgICAgICAgICAgICAgICAgcmVhZF9leGNlbCgndXJfaXJlZGVsbC54bHN4JywgdHJpbV93cyA9IFQpICU+JSBtdXRhdGUoQ291bnR5ID0gJ0lyZWRlbGwnLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpLA0KICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZXhjZWwoJ3VyX2xhbmNhc3Rlci54bHN4JywgdHJpbV93cyA9IFQpICU+JSBtdXRhdGUoQ291bnR5ID0gJ0xhbmNhc3RlcicsIFBlcmlvZCA9IGdzdWIoJ00nLCAnJywgUGVyaW9kKSksDQogICAgICAgICAgICAgICAgICAgICAgcmVhZF9leGNlbCgndXJfbGluY29sbi54bHN4JywgdHJpbV93cyA9IFQpICU+JSBtdXRhdGUoQ291bnR5ID0gJ0xpbmNvbG4nLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpLA0KICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZXhjZWwoJ3VyX21lY2tsZW5idXJnLnhsc3gnLCB0cmltX3dzID0gVCkgJT4lIG11dGF0ZShDb3VudHkgPSAnTWVja2xlbmJ1cmcnLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpLA0KICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZXhjZWwoJ3VyX3Jvd2FuLnhsc3gnLCB0cmltX3dzID0gVCkgJT4lIG11dGF0ZShDb3VudHkgPSAnUm93YW4nLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpLA0KICAgICAgICAgICAgICAgICAgICAgIHJlYWRfZXhjZWwoJ3VyX3N0YW5seS54bHN4JywgdHJpbV93cz1ULCBza2lwPTExKVsxOjI2NixdICU+JSByZW5hbWUoVmFsdWUgPSAnT2JzZXJ2YXRpb24gVmFsdWUnKSAlPiUgbXV0YXRlKENvdW50eSA9ICdTdGFubHknLCBQZXJpb2QgPSBnc3ViKCdNJywnJyxQZXJpb2QpKSAlPiUgc2VsZWN0KC1MYWJlbCksDQogICAgICAgICAgICAgICAgICAgICAgcmVhZF9leGNlbCgndXJfdW5pb24ueGxzeCcsIHRyaW1fd3MgPSBUKSAlPiUgbXV0YXRlKENvdW50eSA9ICdVbmlvbicsIFBlcmlvZCA9IGdzdWIoJ00nLCAnJywgUGVyaW9kKSksDQogICAgICAgICAgICAgICAgICAgICAgcmVhZF9leGNlbCgndXJfeW9yay54bHN4JywgdHJpbV93cyA9IFQpICU+JSBtdXRhdGUoQ291bnR5ID0gJ1lvcmsnLCBQZXJpb2QgPSBnc3ViKCdNJywgJycsIFBlcmlvZCkpKSAlPiUNCiAgbXV0YXRlKFllYXIgPSBhcy5pbnRlZ2VyKFllYXIpLA0KICAgICAgICAgUGVyaW9kID0gYXMuaW50ZWdlcihQZXJpb2QpLA0KICAgICAgICAgRGF0ZSA9IGFzLkRhdGUocGFzdGUoWWVhciwnLScsUGVyaW9kLCAnLTAxJywgc2VwID0gJycpKSwNCiAgICAgICAgIFZhbHVlID0gVmFsdWUvMTAwKSAlPiUNCiAgcmVuYW1lKE1vbnRoID0gUGVyaW9kLA0KICAgICAgICAgVW5lbXBsb3ltZW50ID0gVmFsdWUpDQoNCiMgTWFrZSBpbmNvbWUgZGF0YSBmcmFtZQ0KaW5jb21lIDwtIHJlYWQuY3N2KCdWYWx1ZXMuY3N2JykgJT4lDQogIG11dGF0ZShDb3VudHkgPSBnc3ViKCcgQ291bnR5LCBOb3J0aCBDYXJvbGluYScsICcnLCBDb3VudHkpLA0KICAgICAgICAgQ291bnR5ID0gZ3N1YignIENvdW50eSwgU291dGggQ2Fyb2xpbmEnLCAnJywgQ291bnR5KSkgJT4lDQogIGZpbHRlcihJbmRpY2F0b3IgPT0gJ0luY29tZSAmIEVhcm5pbmdzJywNCiAgICAgICAgIENvdW50eSAlaW4lIGNvdW50aWVzLA0KICAgICAgICAgTWVhc3VyZSAhPSAnSG91c2Vob2xkIEluY29tZTogVG90YWwnKSAlPiUNCiAgZGlzdGluY3QoKQ0KaW5jb21lIDwtIGluY29tZSAlPiUgaW5uZXJfam9pbigoaW5jb21lICU+JSBncm91cF9ieShDb3VudHksIFllYXIpICU+JSBzdW1tYXJpc2UoVG90YWwgPSBzdW0oTnVtZXJhdG9yX3ZhbHVlKSkpLCBieSA9IGMoJ0NvdW50eScsICdZZWFyJykpDQoNCiMgTWFrZSBlZHVjYXRpb24gYXR0YWlubWVudCBkYXRhIGZyYW1lDQplZHVjYXRpb24gPC0gcmVhZC5jc3YoJ1ZhbHVlcy5jc3YnKSAlPiUNCiAgbXV0YXRlKENvdW50eSA9IGdzdWIoJyBDb3VudHksIE5vcnRoIENhcm9saW5hJywgJycsIENvdW50eSksDQogICAgICAgICBDb3VudHkgPSBnc3ViKCcgQ291bnR5LCBTb3V0aCBDYXJvbGluYScsICcnLCBDb3VudHkpKSAlPiUNCiAgZmlsdGVyKEluZGljYXRvciA9PSAnRWR1Y2F0aW9uYWwgQXR0YWlubWVudCcsDQogICAgICAgICBDb3VudHkgJWluJSBjb3VudGllcywNCiAgICAgICAgIE1lYXN1cmUgJWluJSBhdHRhaW5tZW50X2x2bCkgJT4lDQogIGRpc3RpbmN0KCkNCmVkdWNhdGlvbiA8LSBlZHVjYXRpb24gJT4lIGlubmVyX2pvaW4oKGVkdWNhdGlvbiAlPiUgZ3JvdXBfYnkoQ291bnR5LCBZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsID0gc3VtKE51bWVyYXRvcl92YWx1ZSkpKSwgYnkgPSBjKCdDb3VudHknLCAnWWVhcicpKSAlPiUNCiAgbXV0YXRlKE9yZGVyID0gYXMuZmFjdG9yKGNhc2Vfd2hlbigNCiAgICBNZWFzdXJlID09ICdIaWdoZXN0IERlZ3JlZTogTGVzcyB0aGFuIGEgSGlnaCBTY2hvb2wgRGlwbG9tYScgfiAxLA0KICAgIE1lYXN1cmUgPT0gJ0hpZ2hlc3QgRGVncmVlOiBIaWdoIFNjaG9vbCBEaXBsb21hJyB+IDIsDQogICAgTWVhc3VyZSA9PSAnSGlnaGVzdCBEZWdyZWU6IFNvbWUgQ29sbGVnZSwgTm8gRGVncmVlJyB+IDMsDQogICAgTWVhc3VyZSA9PSAiSGlnaGVzdCBEZWdyZWU6IEFzc29jaWF0ZSdzIERlZ3JlZSIgfiA0LA0KICAgIE1lYXN1cmUgPT0gIkhpZ2hlc3QgRGVncmVlOiBCYWNoZWxvcidzIERlZ3JlZSIgfiA1LA0KICAgIE1lYXN1cmUgPT0gIkhpZ2hlc3QgRGVncmVlOiBHcmFkdWF0ZSBvciBQcm9mZXNzaW9uYWwgRGVncmVlIiB+IDYpKSkNCiMgTWFrZSBoZWFsdGggY2FyZSBjb3ZlcmFnZSBkYXRhIGZyYW1lDQpjb3ZlcmFnZSA8LSByZWFkLmNzdignVmFsdWVzLmNzdicpICU+JQ0KICBtdXRhdGUoQ291bnR5ID0gZ3N1YignIENvdW50eSwgTm9ydGggQ2Fyb2xpbmEnLCAnJywgQ291bnR5KSwNCiAgICAgICAgIENvdW50eSA9IGdzdWIoJyBDb3VudHksIFNvdXRoIENhcm9saW5hJywgJycsIENvdW50eSkpICU+JQ0KICBmaWx0ZXIoSW5kaWNhdG9yID09ICdIZWFsdGggQ2FyZSBDb3ZlcmFnZScsDQogICAgICAgICBDb3VudHkgJWluJSBjb3VudGllcykNCiMgTWFrZSBob3VzaW5nIGFnZSBkYXRhIGZyYW1lDQpob3VzaW5nIDwtIHJlYWQuY3N2KCdWYWx1ZXMuY3N2JykgJT4lDQogIG11dGF0ZShDb3VudHkgPSBnc3ViKCcgQ291bnR5LCBOb3J0aCBDYXJvbGluYScsICcnLCBDb3VudHkpLA0KICAgICAgICAgQ291bnR5ID0gZ3N1YignIENvdW50eSwgU291dGggQ2Fyb2xpbmEnLCAnJywgQ291bnR5KSkgJT4lDQogIGZpbHRlcihJbmRpY2F0b3IgPT0gJ0hvdXNpbmcgU3RvY2snLA0KICAgICAgICAgQ291bnR5ICVpbiUgY291bnRpZXMpDQojIE1ha2UgcG92ZXJ0eSBmaWd1cmVzIGRhdGEgZnJhbWUNCnBvdmVydHkgPC0gcmVhZC5jc3YoJ1ZhbHVlcy5jc3YnKSAlPiUNCiAgbXV0YXRlKENvdW50eSA9IGdzdWIoJyBDb3VudHksIE5vcnRoIENhcm9saW5hJywgJycsIENvdW50eSksDQogICAgICAgICBDb3VudHkgPSBnc3ViKCcgQ291bnR5LCBTb3V0aCBDYXJvbGluYScsICcnLCBDb3VudHkpKSAlPiUNCiAgZmlsdGVyKE1lYXN1cmUgPT0gJ0luZGl2aWR1YWxzIGluIFBvdmVydHknLA0KICAgICAgICAgVGhlbWUgPT0gJ1NvY2lhbCBXZWxsLUJlaW5nJywNCiAgICAgICAgIENvdW50eSAlaW4lIGNvdW50aWVzKQ0KIyBNYWtlIHRyYW5zcG9ydGF0aW9uIG1lYW5zIGRhdGEgZnJhbWUNCnRyYW5zcG9ydGF0aW9uIDwtIHJlYWQuY3N2KCdWYWx1ZXMuY3N2JykgJT4lDQogIG11dGF0ZShDb3VudHkgPSBnc3ViKCcgQ291bnR5LCBOb3J0aCBDYXJvbGluYScsICcnLCBDb3VudHkpLA0KICAgICAgICAgQ291bnR5ID0gZ3N1YignIENvdW50eSwgU291dGggQ2Fyb2xpbmEnLCAnJywgQ291bnR5KSkgJT4lDQogIGZpbHRlcihUaGVtZSA9PSAnVHJhbnNwb3J0YXRpb24nLA0KICAgICAgICAgTWVhc3VyZSAhPSAnQ29tbXV0aW5nIE1lYW5zIFRvdGFsJywNCiAgICAgICAgIENvdW50eSAlaW4lIGNvdW50aWVzKQ0KYGBgDQoNCg0KIyBEZW1vZ3JhcGhpY3MNCiMjIFBvcHVsYXRpb24NCmBgYHtyfQ0KcGxvdF9seShjb3VudHlwb3AgJT4lIGZpbHRlcihZRUFSID09IDIwMTkpLCB4ID0gflBPUEVTVElNQVRFLCB5ID0gfkNUWU5BTUUsIHR5cGUgPSAnYmFyJywgY29sb3IgPSB+Q1RZTkFNRSwgY29sb3JzID0gY29sb3JfYSwgb3JpZW50YXRpb24gPSAnaCcpDQoNCnBsb3RfbHkoY291bnR5cG9wLCB4PX5ZRUFSLCB5PX5DSEFOR0UsIGNvbG9yPX5DVFlOQU1FLCB0eXBlPSdzY2F0dGVyJywgbW9kZT0nbGluZXMnLCBjb2xvcnM9Y29sb3JfYSkNCmBgYA0KDQojIyBBZ2UgJiBHZW5kZXINCmBgYHtyLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoPSAxMH0NCnBsb3RfbHkocG9wX2FnZV9nZW5kZXIgJT4lIGZpbHRlcihZRUFSID09IDIwMTcsIENUWU5BTUUgPT0gJ0NoYXJsb3R0ZSBSZWdpb24nLCBHRU5ERVIgPT0gIk1BTEUiKSwNCiAgICAgICAgeT1+REVNTywgeD1+UEVSQ0VOVEFHRSwNCiAgICAgICAgdHlwZT0nYmFyJywgbmFtZSA9ICdNYWxlJykgJT4lDQogIGFkZF90cmFjZShkYXRhID0gcG9wX2FnZV9nZW5kZXIgJT4lIGZpbHRlcihZRUFSID09IDIwMTcsIENUWU5BTUUgPT0gJ0NoYXJsb3R0ZSBSZWdpb24nLCBHRU5ERVIgPT0gIkZFTUFMRSIpLCB5PX5ERU1PLCBuYW1lID0gJ0ZlbWFsZScpDQpgYGANCg0KIyMgUmFjZSAmIEV0aG5pY2l0eQ0KYGBge3J9DQpwbG90X2x5KGV0aHBvcCAlPiUgZmlsdGVyKFlFQVIgPT0gMjAxOSksDQogICAgICAgIHk9fkNUWU5BTUUsIHg9flBPUC9UT1RfUE9QLCBjb2xvcj1+RVRITklDSVRZLA0KICAgICAgICB0eXBlPSdiYXInKSAlPiUNCiAgbGF5b3V0KGJhcm1vZGUgPSAnc3RhY2snKQ0KYGBgDQoNCiMjIFBsYWNlIG9mIEJpcnRoDQpgYGB7cn0NCnBsb3RfbHkoYmlydGhwbGFjZSAlPiUgZmlsdGVyKFllYXIgPT0gMjAxOSksDQogICAgICAgIHk9fkNvdW50eSwgeD1+TnVtZXJhdG9yX3ZhbHVlL1RvdGFsLCBjb2xvcj1+TWVhc3VyZSwNCiAgICAgICAgdHlwZT0nYmFyJykgJT4lDQogIGxheW91dChiYXJtb2RlID0gJ3N0YWNrJykNCmBgYA0KDQoNCg0KIyBFY29ub215DQojIyBVbmVtcGxveW1lbnQNCmBgYHtyfQ0KcGxvdF9seSh1bmVtcGxveW1lbnQsIHg9fkRhdGUsIHk9flVuZW1wbG95bWVudCwgY29sb3I9fkNvdW50eSwgY29sb3JzPWNvbG9yX2EsIHR5cGU9J3NjYXR0ZXInLCBtb2RlPSdsaW5lcycpDQoNCnBsb3RfbHkodW5lbXBsb3ltZW50ICU+JSBmaWx0ZXIoWWVhcj09MjAxNSwgTW9udGg9PTYpLCB4PX5VbmVtcGxveW1lbnQsIHk9fkNvdW50eSwgY29sb3I9fkNvdW50eSwgY29sb3JzPWNvbG9yX2EsIHR5cGU9J2JhcicpDQpgYGANCg0KIyMgSW5jb21lDQpgYGB7cn0NCiMjIyMgREZzIGZyb20gVmFsdWVzLmNzdiBhcmUgbWlzc2luZyBBbnNvbiwgQ2hlc3RlciwgYW5kIFN0YW5seSBDb3VudGllcw0KZ2dwbG90KGluY29tZSAlPiUgZmlsdGVyKFllYXIgPT0gMjAxNCksIGFlcyh4ID0gQ291bnR5LCB5ID0gKE51bWVyYXRvcl92YWx1ZSAvIFRvdGFsKSwgZmlsbCA9IE1lYXN1cmUpLCBwb3NpdGlvbiA9ICdmaWxsJykgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKw0KICBjb29yZF9mbGlwKCkNCmBgYA0KDQojIEVkdWNhdGlvbg0KIyMgRWR1Y2F0aW9uYWwgQXR0YWlubWVudA0KYGBge3J9DQpnZ3Bsb3QoYXJyYW5nZShlZHVjYXRpb24sIE9yZGVyKSAlPiUgZmlsdGVyKFllYXIgPT0gMjAxNCksIGFlcyh4ID0gQ291bnR5LCB5ID0gKE51bWVyYXRvcl92YWx1ZSAvIFRvdGFsKSwgZmlsbCA9IE9yZGVyKSwgcG9zaXRpb24gPSAnZmlsbCcpICsNCiAgZ2VvbV9jb2woKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgY29vcmRfZmxpcCgpKw0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKGxhYmVscyA9IGF0dGFpbm1lbnRfbHZsLCBuYW1lID0gJycpDQpgYGANCg0KIyBIZWFsdGgNCiMjIEhlYWx0aCBDYXJlIENvdmVyYWdlDQpgYGB7cn0NCmNvdmVyYWdlICU+JSBmaWx0ZXIoTWVhc3VyZSA9PSAiSGVhbHRoIEluc3VyYW5jZSBUb3RhbCIsIFllYXIgPT0gMjAxNykgJT4lDQogIGdncGxvdCguLCBhZXMoeCA9IENvdW50eSwgeSA9IE51bWVyYXRvcl92YWx1ZSwgZmlsbCA9IENvdW50eSkpKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArDQogIGNvb3JkX2ZsaXAoKQ0KY292ZXJhZ2UgJT4lIGZpbHRlcihZZWFyID09IDIwMTcsICEoTWVhc3VyZSAlaW4lIGMoIkhlYWx0aCBJbnN1cmFuY2UgVG90YWwiLCAiUGVvcGxlIHdpdGggSGVhbHRoIEluc3VyYW5jZSIpKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IENvdW50eSwgeSA9IE51bWVyYXRvcl92YWx1ZSwgZmlsbCA9IE1lYXN1cmUsIHBvc2l0aW9uID0gTWVhc3VyZSkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYSkgKw0KICBjb29yZF9mbGlwKCkNCmBgYA0KIyBIb3VzaW5nDQojIyBIb3VzaW5nIEFnZQ0KYGBge3J9DQpob3VzaW5nICU+JSBmaWx0ZXIoWWVhciA9PSAyMDE3KSAlPiUNCiAgZ2dwbG90KGFlcyh4PSBDb3VudHksIHkgPSBZZWFyLU51bWVyYXRvcl92YWx1ZSwgZmlsbCA9IENvdW50eSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGNvb3JkX2ZsaXAoKQ0KYGBgDQojIFNvY2lhbCBXZWxsLUJlaW5nDQojIyBQb3ZlcnR5DQpgYGB7cn0NCnBvdmVydHkgJT4lIGZpbHRlcihZZWFyID09IDIwMTApICU+JQ0KICBnZ3Bsb3QoLiwgYWVzKHggPSBDb3VudHksIHkgPSBOdW1lcmF0b3JfdmFsdWUvRGVub21pbmF0b3JfdmFsdWUsIGZpbGwgPSBDb3VudHkpKSArDQogIGdlb21fY29sKCkgKw0KICBjb29yZF9mbGlwKCkNCmBgYA0KIyBUcmFuc3BvcnRhdGlvbg0KIyNDb21tdXRpbmcgTW9kZXMNCmBgYHtyLCBldmFsPUZBTFNFfQ0KIyBXYXkgdG9vIG1hbnkgbWlzc2luZyB2YWx1ZXMgdG8gY3JlYXRlIGEgc3Vic3RhbnRpdmUgdmlzdWFsaXphdGlvbi4NCnRyYW5zcG9ydGF0aW9uICU+JSBmaWx0ZXIoWWVhciA9PSAyMDE0KSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gQ291bnR5LCB5ID0gTnVtZXJhdG9yX3ZhbHVlLCBmaWxsID0gTWVhc3VyZSwgcG9zaXRpb24gPSBNZWFzdXJlKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArDQogIGNvb3JkX2ZsaXAoKQ0KYGBgDQoNCg0KDQoNCg==